package com.shangguosha.model;

import com.shangguosha.core.GameObject;
import com.shangguosha.game.GameContext;
import com.shangguosha.model.enums.Gender;
import com.shangguosha.model.enums.Kingdom;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.ArrayList;
import java.util.List;

/**
 * 角色类
 */
@Data
@EqualsAndHashCode(callSuper = true)
public abstract class Character extends GameObject {
    protected Kingdom kingdom;
    protected Gender gender;
    protected int maxHp;
    protected int currentHp;
    protected List<Skill> skills;
    protected List<Card> handCards;
    protected List<Card> equipments;
    protected boolean isAlive;
    protected boolean isChained;
    protected boolean isFlipped;
    
    public Character(String id, String name, Kingdom kingdom, Gender gender, int maxHp) {
        super(id, name);
        this.kingdom = kingdom;
        this.gender = gender;
        this.maxHp = maxHp;
        this.currentHp = maxHp;
        this.skills = new ArrayList<>();
        this.handCards = new ArrayList<>();
        this.equipments = new ArrayList<>();
        this.isAlive = true;
        this.isChained = false;
        this.isFlipped = false;
        
        // 设置事件总线
        GameContext gameContext = GameContext.getInstance();
        if (gameContext != null) {
            setEventBus(gameContext.getEventBus());
        }
    }
    
    @Override
    public void onCreate() {
        super.onCreate();
        initializeSkills();
    }
    
    /**
     * 初始化角色技能 - 子类实现
     */
    protected abstract void initializeSkills();
    
    /**
     * 受到伤害
     */
    public void takeDamage(int damage) {
        if (!isAlive) return;
        
        currentHp -= damage;
        emit("damage_taken", this, damage);
        
        if (currentHp <= 0) {
            currentHp = 0;
            enterDyingState();
        }
    }
    
    /**
     * 恢复体力
     */
    public void heal(int amount) {
        if (!isAlive) return;
        
        int oldHp = currentHp;
        currentHp = Math.min(currentHp + amount, maxHp);
        
        if (currentHp > oldHp) {
            emit("healed", this, currentHp - oldHp);
        }
    }
    
    /**
     * 进入濒死状态
     */
    private void enterDyingState() {
        emit("dying", this);
        
        if (currentHp <= 0) {
            die();
        }
    }
    
    /**
     * 死亡
     */
    public void die() {
        if (!isAlive) return;
        
        isAlive = false;
        emit("death", this);
        onDestroy();
    }
    
    /**
     * 摸牌
     */
    public void drawCard(Card card) {
        if (card != null) {
            handCards.add(card);
            emit("card_drawn", this, card);
        }
    }
    
    /**
     * 弃牌
     */
    public boolean discardCard(Card card) {
        if (handCards.remove(card)) {
            emit("card_discarded", this, card);
            return true;
        }
        return false;
    }
    
    /**
     * 使用卡牌
     */
    public boolean useCard(Card card, Character target) {
        if (!handCards.contains(card)) {
            return false;
        }
        
        handCards.remove(card);
        emit("card_used", this, card, target);
        return true;
    }
    
    /**
     * 装备卡牌
     */
    public void equipCard(Card equipment) {
        if (equipment != null) {
            equipments.add(equipment);
            emit("card_equipped", this, equipment);
        }
    }
    
    /**
     * 卸下装备
     */
    public boolean unequipCard(Card equipment) {
        if (equipments.remove(equipment)) {
            emit("card_unequipped", this, equipment);
            return true;
        }
        return false;
    }
    
    /**
     * 获取手牌数量
     */
    public int getHandCardCount() {
        return handCards.size();
    }
    
    /**
     * 是否有指定卡牌
     */
    public boolean hasCard(Card card) {
        return handCards.contains(card);
    }
    
    /**
     * 是否有指定技能
     */
    public boolean hasSkill(String skillName) {
        return skills.stream().anyMatch(skill -> skill.getName().equals(skillName));
    }
    
    /**
     * 获取技能
     */
    public Skill getSkill(String skillName) {
        return skills.stream()
                .filter(skill -> skill.getName().equals(skillName))
                .findFirst()
                .orElse(null);
    }
    
    /**
     * 添加技能
     */
    public void addSkill(Skill skill) {
        if (skill != null && !hasSkill(skill.getName())) {
            skills.add(skill);
            skill.setOwner(this);
            emit("skill_added", this, skill);
        }
    }
    
    /**
     * 移除技能
     */
    public boolean removeSkill(String skillName) {
        Skill skill = getSkill(skillName);
        if (skill != null && skills.remove(skill)) {
            skill.setOwner(null);
            emit("skill_removed", this, skill);
            return true;
        }
        return false;
    }
    
    // Getters and Setters
    public Kingdom getKingdom() {
        return kingdom;
    }
    
    public void setKingdom(Kingdom kingdom) {
        this.kingdom = kingdom;
    }
    
    public Gender getGender() {
        return gender;
    }
    
    public void setGender(Gender gender) {
        this.gender = gender;
    }
    
    public int getMaxHp() {
        return maxHp;
    }
    
    public void setMaxHp(int maxHp) {
        this.maxHp = maxHp;
    }
    
    public int getCurrentHp() {
        return currentHp;
    }
    
    public void setCurrentHp(int currentHp) {
        this.currentHp = Math.max(0, Math.min(currentHp, maxHp));
    }
    
    public List<Skill> getSkills() {
        return new ArrayList<>(skills);
    }
    
    public List<Card> getHandCards() {
        return new ArrayList<>(handCards);
    }
    
    public List<Card> getEquipments() {
        return new ArrayList<>(equipments);
    }
    
    public boolean isAlive() {
        return isAlive;
    }
    
    public void setAlive(boolean alive) {
        isAlive = alive;
    }
    
    public boolean isChained() {
        return isChained;
    }
    
    public void setChained(boolean chained) {
        this.isChained = chained;
        emit("chain_state_changed", this, chained);
    }
    
    public boolean isFlipped() {
        return isFlipped;
    }
    
    public void setFlipped(boolean flipped) {
        this.isFlipped = flipped;
        emit("flip_state_changed", this, flipped);
    }
    
    @Override
    public String toString() {
        return String.format("Character{name='%s', kingdom=%s, hp=%d/%d, alive=%s}", 
                getName(), kingdom, currentHp, maxHp, isAlive);
    }
}